package com.hh.admin.controller;

import java.awt.image.BufferedImage;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.shiro.authc.CredentialsException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.hibernate.validator.constraints.NotBlank;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;

import com.hh.admin.exception.LoginErrorException;
import com.hh.admin.service.ISysUserService;
import com.hh.admin.view.LoginView;
import com.hh.core.common.BaseController;
import com.hh.core.common.constant.SysConstant;
import com.hh.core.enums.ExceptionEnum;
import com.hh.core.log.LogManager;
import com.hh.core.log.LogTaskFactory;
import com.hh.core.property.BaseProperty;
import com.hh.core.shiro.entity.ShiroUser;
import com.hh.core.shiro.util.ShiroUtil;
import com.hh.core.util.HttpCoreUtil;

/**
 * 
 * @ClassName: LoginController
 * @Description: TODO(用户登录控制层)
 * @author hxn
 * @date 2018年1月19日 下午2:18:14
 *
 */
@Controller
@Validated
public class LoginController extends BaseController {

	@Autowired
	ISysUserService sysUserService;

	@Autowired
	BaseProperty baseProperty;

	private static final Log log = LogFactory.get();

	/**
	 * 
	 * @Title: index
	 * @Description: 重定向到登录页面
	 * @param @return 设定文件
	 * @return String 返回类型
	 * @author hxn
	 * @date 2018年1月30日 下午3:21:37
	 * @throws
	 */
	@RequestMapping(value = "/", method = RequestMethod.GET)
	public String index() {
		return REDIRECT + LoginView.LOGIN_PATH; // 重定向到/login
	}

	/**
	 * 
	 * @Title: login
	 * @Description: 跳转到登录页面
	 * @param @return 设定文件
	 * @return String 返回类型
	 * @author hxn
	 * @date 2018年1月19日 下午2:35:50
	 * @throws
	 */
	@RequestMapping(value = "/login", method = RequestMethod.GET)
	public String login() {
		// 用户已登录
		if (ShiroUtil.isAuthenticated()
				|| ObjectUtil.isNotNull(ShiroUtil.getUser())) {
			return REDIRECT + LoginView.ADMIN_PAHT; // 重定向到/admin
		}
		return LoginView.LOGIN_VIEW;
	}

	/**
	 * 
	 * @Title: logout
	 * @Description: 用户注销
	 * @param @return 设定文件
	 * @return String 返回类型
	 * @author hxn
	 * @date 2018年2月7日 下午2:38:49
	 * @throws
	 */
	@RequestMapping(value = "/logout", method = RequestMethod.GET)
	public String loginOut() {
		ShiroUtil.getSubject().logout();
		return REDIRECT + LoginView.LOGIN_PATH; // 重定向到/login
	}

	/**
	 * 
	 * @Title: formLogin
	 * @Description: 表单提交登录
	 * @param @param username
	 * @param @param password
	 * @param @param captcha
	 * @param @param request
	 * @param @return 设定文件
	 * @return String 返回类型
	 * @author hxn
	 * @date 2018年2月7日 下午2:33:11
	 * @throws
	 */
	@RequestMapping(value = "/login", method = RequestMethod.POST)
	public String formLogin(@NotBlank(message = "用户名不能为空") String username,
			@NotBlank(message = "密码不能为空") String password, String captcha,
			HttpServletRequest request) {
		// 是否开启验证码
		if (baseProperty.getCaptchaOpen()) {
			String captchaCode = request.getSession()
					.getAttribute(SysConstant.CAPTCHA_CODE).toString();
			request.getSession().removeAttribute(SysConstant.CAPTCHA_CODE);
			if (!StrUtil.equalsIgnoreCase(captchaCode, captcha)) {
				log.info("验证码错误!");
				throw new LoginErrorException(ExceptionEnum.CAPTCHA_ERROR);// 验证码错误
			}
		}

		Subject currentUser = ShiroUtil.getSubject();
		UsernamePasswordToken token = new UsernamePasswordToken(username,
				password.toCharArray());
		String ip = HttpCoreUtil.getIpAddr(request);
		try {
			currentUser.login(token);
		} catch (CredentialsException e) {
			LogManager.me().executeLog(
					LogTaskFactory.loginLog(3, 0L, ip, username));
			throw new LoginErrorException(ExceptionEnum.USER_PWD_ERROR);// 用户密码错误
		}
		ShiroUser shiroUser = ShiroUtil.getUser();

		request.getSession().setAttribute("userName", shiroUser.getName());
		request.getSession().setAttribute("ip", ip);
		request.getSession().setAttribute("id", shiroUser.getId());
		request.getSession().setAttribute("account", shiroUser.getAccount());
		// shiro session 标识
		ShiroUtil.getSession().setAttribute(SysConstant.SESSION_FLAG, true);

		LogManager.me().executeLog(
				LogTaskFactory.loginLog(1, shiroUser.getId(), ip,
						shiroUser.getAccount()));
		return REDIRECT + LoginView.ADMIN_PAHT;
	}

	/**
	 * 
	 * @Title: captcha
	 * @Description: 生成验证码
	 * @param 设定文件
	 * @return void 返回类型
	 * @author hxn
	 * @date 2018年1月19日 下午3:22:30
	 * @throws
	 */
	@RequestMapping("/captcha")
	public void captcha(HttpServletRequest request, HttpServletResponse response) {
		response.setDateHeader("Expires", 0);
		// Set standard HTTP/1.1 no-cache headers.
		response.setHeader("Cache-Control",
				"no-store, no-cache, must-revalidate");
		// Set IE extended HTTP/1.1 no-cache headers (use addHeader).
		response.addHeader("Cache-Control", "post-check=0, pre-check=0");
		// Set standard HTTP/1.0 no-cache header.
		response.setHeader("Pragma", "no-cache");
		// return a jpeg
		response.setContentType("image/jpeg");
		// 创建线干扰的验证码(长，高，字符个数，干扰线条数)
		LineCaptcha captcha = CaptchaUtil.createLineCaptcha(125, 45, 4, 10);
		BufferedImage bi = captcha.getImage();
		// 验证码保存到session
		request.getSession().setAttribute(SysConstant.CAPTCHA_CODE,
				captcha.getCode());
		ServletOutputStream out = null;
		try {
			out = response.getOutputStream();
		} catch (IOException e) {
			e.printStackTrace();
		}

		try {
			// 输出图片
			ImageIO.write(bi, "jpg", out);
		} catch (IOException e) {
			e.printStackTrace();
		}
		try {
			try {
				out.flush();
			} catch (IOException e) {
				e.printStackTrace();
			}
		} finally {
			try {
				out.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}
